package first.endtoend

import first.endtoend.messages.MessageCode
import net.sf.json.JSONObject
import org.springframework.dao.DataIntegrityViolationException

import java.text.SimpleDateFormat

class AidController
{

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
    def scaffold = true
    def sendNotificationService

    def index()
    {
        redirect(action: "list", params: params)
    }

    def list(Integer max)
    {
        params.max = Math.min(max ?: 10, 100)

        //verify validity of aids
        def allAids = Aid.findAll()
        Date curentDate = new Date()
        if (allAids)
        {
            allAids.each {
                it.valid = true
                it.save()
                if (it.endDate < curentDate)
                {
                    it.valid = false
                    it.save()
                } else
                {

                }
            }

            allExpiredAids(allAids)
        }



        [aidInstanceList: Aid.list(params), aidInstanceTotal: Aid.count()]
    }

    def create()
    {

        [aidInstance: new Aid(params)]
    }

    def familyService

    def save()
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd")
        Date startDate = sdf.parse(params.startDate)
        Date endDate = sdf.parse(params.endDate)

        if (!verifyPeriodAid(startDate, endDate))
        {
            flash.message = message(code: 'invalid.aid.message', default: "Invalid Aid for this period")
            render(view: "create")
            return
        }
        Category categoryInstance = Category.findById(params.category.id)
        def aidInstance = new Aid(startDate: startDate, endDate: endDate, category: categoryInstance)
        if (!aidInstance.save(flush: true))
        {
            render(view: "create", model: [aidInstance: aidInstance])
            return
        }


        flash.message = message(code: 'default.created.message', args: [message(code: 'aid.label', default: 'Aid'), aidInstance.id])
        redirect(action: "show", id: aidInstance.id)


    }

    def shareAid(Long id)
    {
        def aidInstance = Aid.get(id)
        if (!aidInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "list")
            return
        }
        //share this aid to all families in the category
        //1. get all famlilies who belong to this category
        def families = aidInstance.category.families
        //2. get products for this category
        def aidProducts = aidInstance.category.categorieProducts
        //3. for each family whe search the current portfolio

        Agent agentInstance
        FairPricesShop fpsInstance
        Notification notificationInstance

        families.each {
            def portfolio = familyService.getPortfolio(it, aidInstance.startDate, aidInstance.endDate)
            if (portfolio)
            {
                //create a new aid for this family , aid means in this case portfoliodetails
                //for each products we create a portfolio details
                aidProducts.each { aidProduct ->
                    def portfolioDetail = new PortfolioDetail(aid: aidInstance, product: aidProduct.product, portfolio: portfolio, quantity: aidProduct.quantity, reduction: aidProduct.reduction)
                    if (portfolioDetail.save(flush: true))
                    {
                        flash.message = message(code: 'default.aid.generate.message', args: [message(code: 'aid.label', default: 'Aid'), id, families.size()])
                    } else
                    {
                        //TODO:handle errors while saving portfolio detail
                        def error = ""
                        if (portfolioDetail.hasErrors())
                        {
                            portfolioDetail.errors.each {
                                println it
                                error += it.toString()
                            }
                        }
                        flash.message = message(code: 'default.aid.generate.error.message', args: [message(code: 'aid.label', default: 'Aid'), id, error])
                    }
                }

            } else
            {
                //TODO:manage errors when family has no portfolio
                flash.message = message(code: 'default.aid.generate.error.message', args: [message(code: 'aid.label', default: 'Aid'), id, "Error while saving portfolio"])
            }

            //for these families sharing this new aid, find fps related and agent serving them to add notification


            fpsInstance = it.fps
            println("fps here is " + fpsInstance)
            if (fpsInstance)
            {
                agentInstance = fpsInstance.agent

                if (agentInstance && it.rationCard != null)
                {
                    notificationInstance = new Notification(idModel: aidInstance.id, code: MessageCode.AID_ADD.value(), modelName: Aid.getSimpleName(), agent: agentInstance, description: message(code: 'default.aid.generate.message')).save()
                } else
                {

                }

            }


        }

        render(view: "show", model: [aidInstance: aidInstance])
        // return
    }

    def show(Long id)
    {
        def aidInstance = Aid.get(id)
        if (!aidInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "list")
            return
        }

        [aidInstance: aidInstance]
    }

    def edit(Long id)
    {
        def aidInstance = Aid.get(id)
        if (!aidInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "list")
            return
        }

        [aidInstance: aidInstance]
    }

    def update(Long id, Long version)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd")
        Date startDate = sdf.parse(params.startDate)
        Date endDate = sdf.parse(params.endDate)
        def aidInstance = Aid.get(id)
        if (!aidInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "list")
            return
        }
        if (version != null)
        {
            if (aidInstance.version > version)
            {
                aidInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                        [message(code: 'aid.label', default: 'Aid')] as Object[],
                        "Another user has updated this Aid while you were editing")
                render(view: "edit", model: [aidInstance: aidInstance])
                return
            }
        }
        if (!verifyPeriodAid(startDate, endDate))
        {
            flash.message = message(code: 'invalid.aid.message', default: "Invalid Aid for this period")
            render(view: "edit", model: [aidInstance: aidInstance])
            return
        }

        aidInstance.startDate = startDate
        aidInstance.endDate = endDate

        if (!aidInstance.save(flush: true))
        {
            render(view: "edit", model: [aidInstance: aidInstance])
            return
        }


        flash.message = message(code: 'default.updated.message', args: [message(code: 'aid.label', default: 'Aid'), aidInstance.id])
        redirect(action: "show", id: aidInstance.id)
    }

    def delete(Long id)
    {
        def aidInstance = Aid.get(id)
        if (!aidInstance)
        {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "list")
            return
        }

        def families = aidInstance.category.families
        FairPricesShop fpsInstance
        Notification notificationInstance
        def details = PortfolioDetail.findAllByAid(aidInstance)
        try
        {

            PortfolioDetail.deleteAll(details)

            aidInstance.delete(flush: true)
            families.each {
                fpsInstance = it.fps
                println("fps here is " + fpsInstance)
                if (fpsInstance)
                {
                    for (agentInstance in fpsInstance.agents)
                    {
                        if (agentInstance && it.rationCard != null)
                        {
                            notificationInstance = new Notification(idModel: aidInstance.id, code: MessageCode.AID_DELETE.value(), modelName: Aid.getSimpleName(), agent: agentInstance).save()
                        } else
                        {

                        }
                    }
                }
            }

            flash.message = message(code: 'default.deleted.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e)
        {
            flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'aid.label', default: 'Aid'), id])
            redirect(action: "show", id: id)
        }
    }

    /*
     this method returns true if aid is valid on this period,
      */

    def verifyPeriodAid(Date startDate, Date endDate)
    {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd")
        startDate = sdf.parse(params.startDate)
        endDate = sdf.parse(params.endDate)

        def validAid = true
        //this control is added in order to test if there is already an aid in the same period
        Category categoryInstance = Category.findById(params.category.id)
        def allAids
        if (categoryInstance)
        {
            allAids = Aid.findAllByCategory(categoryInstance)
        } else
        {
            //no category found
        }

        if (allAids != null)
        {
            allAids.each {
                if (validAid == true)
                    if (startDate <= it.startDate || (startDate >= it.startDate && startDate <= it.endDate) || startDate >= endDate)
                    {
                        println("**** CANNOT ADD THIS AID FOR THIS PERIOD!!!")
                        validAid = false
                        return
                    }
            }
        } else if (startDate >= endDate)
        {
            println("**** CANNOT ADD THIS AID FOR THIS PERIOD!!!")
            validAid = false
            return
        }

        return validAid
    }

    /*
 this method save notifications related aids that has expired
  */

    def allExpiredAids(def listAids)
    {


        Notification notif
        NotificationView notification
        //find agents responsible for these aids
        List<Agent> agents = new ArrayList<Agent>()
        List<Long> listIdAid = new ArrayList<Long>()
        List<NotificationView> allNotifsToSend = new ArrayList<NotificationView>()

        listAids.each { aid ->
            if (aid.category.families)
            {
                aid.category.families.each { family ->
                    if (family.fps)
                    {
                        for (agent in family.fps.agents)
                        {
                            agents.add(agent)
                        }
                    } else
                    {

                    }

                }
            }

            if (aid.valid == false)
            {
                notif = new Notification(idModel: aid.id, code: MessageCode.AID_DELETE.value(), modelName: Aid.getSimpleName(), description: message(code: 'aid.expired.message', default: "this aid has expired!")).save()
                listIdAid.add(aid.id)
                notification = new NotificationView(code: MessageCode.AID_DELETE.value(), data: listIdAid)
                allNotifsToSend.add(notification)

            } else
            {
            }
        }


        JSONObject jsonNotif
        allNotifsToSend.each {
            jsonNotif = JsonHelper.createJsonObject(it)
            sendNotificationService.sendNotificationToAll(agents, jsonNotif.toString())
        }
    }


}